#lang racket
(provide define-lock-template)
;; This module provides a macro for writing a template for a lock
#|
(define-lock-template (name arg-name ...) [((predicate-identifiers ...) (append-identifiers ...) (constant-identifiers))
                        template])
->
[(name (predicate-functions ...) (append-functions ...) (const-functions ...)) -> lock]

CONVENTION: templates end in a $

examples:
> (define-lock-template (append n) 
   [((equal) (plus) (con1 con2))
    (equal (plus n con1) con2)])   
> (define plus-lock$ (append (=) (+) (1 2)))
> (plus-lock$ 1)
#t
> (plus-lock$ 2)
'((= #<procedure:=>) (+ #<procedure:+>) (n 2) (const 1) (const 2))
> (plus-lock$ "string")
(list
 'exeption:
 (exn:fail:contract "+: expects type <number> as 1st argument, given: \"string\"; other arguments were: 1" #<continuation-mark-set>)
 'binding-list:
 '((= #<procedure:=>) (+ #<procedure:+>) (n "string") (const 1) (const 2)))
|#
(require (for-syntax syntax/parse) "lock.rkt")

(define-syntax (define-lock-template stx)
  (syntax-parse stx
    #:literals (stx)
    [(define-lock-template (name arg ...)
       [((preds ...) (appends ...) (consts ...))
       template])
     #'(define-syntax (name stx) 
         (syntax-parse stx
           [(name (preds ...) (appends ...) (consts ...))
            #'(lambda-lock (arg ...)
                template)]))]))